﻿// Ignacio Quijas
// http://connectedenterprise.wordpress.com
// Description: BizTalk 2010 functoid that consumes a REST Service
// Last Modification Date: July 2012
//
using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.BizTalk.BaseFunctoids;
using System.Reflection;
using System.Net;
using System.IO;

namespace BizTalk.MapperExtensions.RESTFunctoids
{
    [Serializable]
    public class RESTServiceConsume : BaseFunctoid
    {
        public RESTServiceConsume()
            : base()
        {
            //ID for this functoid
            this.ID = 10001;

            // resource assembly must be ProjectName.ResourceName if building with VS.Net
            SetupResourceAssembly("BizTalk.MapperExtensions.RESTFunctoids.RESTFunctoidsResources", Assembly.GetExecutingAssembly());

            //Setup the Name, ToolTip, Help Description, and the Bitmap for this functoid
            SetName("IDS_RESTSERVICECONSUME_NAME");
            SetTooltip("IDS_RESTSERVICECONSUME_TOOLTIP");
            SetDescription("IDS_RESTSERVICECONSUME_DESCRIPTION");
            SetBitmap("IDS_RESTSERVICECONSUME_BITMAP");

            //category for this functoid. This functoid goes under the String Functoid Tab in the
            this.Category = FunctoidCategory.None;

            // Set the limits for the number of input parameters. This example: 4 parameters
            this.SetMinParams(4);
            this.SetMaxParams(4);

            // Add one line of code as set out below for each input param. For multiple input params, each line would be identical.
            AddInputConnectionType(ConnectionType.All); //first input
            AddInputConnectionType(ConnectionType.All); //second input
            AddInputConnectionType(ConnectionType.All); //third input
            AddInputConnectionType(ConnectionType.All); //fourth input

            // The functoid output can go to any node type.
            this.OutputConnectionType = ConnectionType.All;

            // Set the function name that is to be called when invoking this functoid.
            // To test the map in Visual Studio, this functoid does not need to be in the GAC.
            // If using this functoid in a deployed BizTalk app. then it must be in the GAC
            SetExternalFunctionName(GetType().Assembly.FullName, GetType().FullName, "RESTConsume");
        }

        /// <summary>
        /// The real operation to be executed by the functoid
        /// </summary>
        public string RESTConsume(string uri, string method, string timeout, string messageRequest)
        {
            try
            {
                bool error = false;
                string response = "";

                WebRequest webRequest = WebRequest.Create(uri);
                ((HttpWebRequest)webRequest).UserAgent = @"Mozilla/5.0 (Windows; Windows NT 6.1) AppleWebKit/534.23 (KHTML, like Gecko) Chrome/11.0.686.3 Safari/534.23";
                webRequest.ContentType = @"text/xml;charset=""utf-8""";
                webRequest.Method = method;
                if (timeout == "") webRequest.Timeout = 300000;
                else webRequest.Timeout = Int32.Parse(timeout);
                byte[] bytes = Encoding.ASCII.GetBytes(messageRequest);
                Stream os = null;
                StreamReader sr = null;

                if (method == "POST" || method == "PUT")
                {
                    try
                    { // send the Post
                        webRequest.ContentLength = bytes.Length;   //Count bytes to send
                        os = webRequest.GetRequestStream();
                        os.Write(bytes, 0, bytes.Length);         //Send it
                    }
                    catch (WebException ex)
                    {
                        error = true;
                    }
                    finally
                    {
                        if (os != null)
                        {
                            os.Close();
                        }
                    }
                }

                if (error == false && method != "PUT")
                    try
                    { // get the response
                        WebResponse webResponse = webRequest.GetResponse();
                        if (webResponse != null)
                        {
                            sr = new StreamReader(webResponse.GetResponseStream());
                            response = sr.ReadToEnd().Trim();
                        }
                        webResponse.Close();
                    }
                    catch (WebException ex)
                    {
                        error = true;
                    }
                    finally
                    {
                        if (sr != null)
                        {
                            sr.Close();
                        }
                    }

                return response;
            }
            catch (Exception ex)
            {
                return "";
            }
        }
    }
}
